package com.seata.demo.util.handler;

import java.util.List;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import com.seata.demo.util.res.Resp;

import org.hibernate.validator.internal.engine.ConstraintViolationImpl;
import org.springframework.validation.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.method.annotation.*;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.MissingRequestHeaderException;
import org.springframework.web.HttpMediaTypeNotSupportedException;

/**
* 
*/
@Slf4j
@RestControllerAdvice
public class DefaultExceptionHandler {
	
    @ExceptionHandler(value = Exception.class)
    public Resp<?> handleException(HttpServletRequest request, Exception e) {
    	log.error("", e);
    	return Resp.error(e.getMessage());
    }

	/**
     * JSON格式转换错误
     * @author zg
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler(value = InvalidFormatException.class)
    public Resp<?> handleMethodArgumentTypeMismatchException(HttpServletRequest request, InvalidFormatException e) {
        log.warn("", e);
    	return Resp.error("json格式错误");
    }
    
    /**
     * 处理参数类型错误
     * @author zg
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler(value = MethodArgumentTypeMismatchException.class)
    public Resp<?> handleMethodArgumentTypeMismatchException(HttpServletRequest request, MethodArgumentTypeMismatchException e) {
        log.warn("", e);
    	return Resp.error("参数类型错误");
    }
    
    /**
     * 处理请求头参数不传
     * @author zg
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    public Resp<?> handleMissingServletRequestParameterException(HttpServletRequest request, MissingServletRequestParameterException e) {
        log.warn("", e);
    	return Resp.error("参数类型错误");
    }
    
    /**
     * 处理请求头参数不传
     * @author zg
     * @param request
     * @param e
     * @return
     */
	@ExceptionHandler(value = MissingRequestHeaderException.class)
	public Resp<?> handleMissingRequestHeaderException(HttpServletRequest request, MissingRequestHeaderException e) {
	    log.warn("", e);
	    return Resp.error("参数类型错误");
	}
	
	@ExceptionHandler(value = HttpMediaTypeNotSupportedException.class)
	public Resp<?> handleHttpMediaTypeNotSupportedException(HttpServletRequest request, HttpMediaTypeNotSupportedException e) {
	    log.warn("", e);
	    return Resp.error("不支持的媒体类型");
	}
    
    /**
     * JSR-303 Bean校验  @RequestBody 之前加 @Validated
     * @author zg
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Resp<?> handleMethodArgumentNotValidException(HttpServletRequest request, MethodArgumentNotValidException e) {
        log.warn("", e);
		BindingResult bindingResult = e.getBindingResult();
		FieldError error = bindingResult.getFieldError();
		String errMsg = error.getDefaultMessage();
		return Resp.error(errMsg);
    }
    
    /**
     * 对 @RequestParams 参数进行校验，需在Controller上加 @Validated
     * @author zg
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler(value = ConstraintViolationException.class)
    public Resp<?> handleConstraintViolationException(HttpServletRequest request, ConstraintViolationException e) {
        log.warn("", e);
    	String errMsg = null;
		/*System.out.println("1-" + e.getMessage());
		System.out.println("2-" + e.getLocalizedMessage());
		System.out.println("3-" + e.getConstraintViolations());
		System.out.println("4-" + e.getConstraintViolations().size());*/
    	//System.out.println("3-{}" + e.);
    	Set<ConstraintViolation<?>> set = e.getConstraintViolations();
    	if(!set.isEmpty() && set.size() > 0) {
    		Object[] cvs = set.toArray();
    		ConstraintViolationImpl<?> cv = (ConstraintViolationImpl<?>) cvs[0];
    		errMsg = cv.getMessage();
    	} else {
    		errMsg = e.getMessage();
    	}
    	return Resp.error(errMsg);
    }
    
    /**
     * Get 方法接受Bean参数时获取校验信息，需在参数 Bean 前加 @Validated
     * @author zg
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler(value = BindException.class)
    public Resp<?> handleBindException(HttpServletRequest request, BindException e) {
        log.warn("", e);
    	BindingResult bindingResult = e.getBindingResult();
    	List<FieldError> fieldErrors = bindingResult.getFieldErrors();
    	FieldError fe = fieldErrors.get(0);
    	String errMsg = fe.getDefaultMessage();
    	return Resp.error(errMsg);
    }
    
    /**
     * 错误的请求方法
     * @author zg
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
    public Resp<?> handleHttpRequestMethodNotSupportedException(HttpServletRequest request, HttpRequestMethodNotSupportedException e) {
        log.warn("", e);
		return Resp.error("不支持的请求方法");
    }
    
    /**
     * 处理404错误
     * @author zg
     * @param request
     * @param e
     * @return
     */
    /*@ExceptionHandler(value = NoHandlerFoundException.class)
    public Resp handleNoHandlerFoundException(HttpServletRequest request, NoHandlerFoundException e) {
    	printLog(request, e);
    	return new Resp(ResCode.URL_NOT_FOUND);
    }*/
    
    
}
